/*
 * Copyright (c) 2024 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 * http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * ---------------------------------------------------------------------------------------
 *
 * imcu_cache_mgr.h
 * routines to support ColStore
 *
 *
 * IDENTIFICATION
 * src/include/access/imcs/imcu_cache_mgr.h
 *
 * ---------------------------------------------------------------------------------------
 */

#ifndef IMCUCACHEMGR_H
#define IMCUCACHEMGR_H

#include "postgres.h"
#include "knl/knl_variable.h"
#include "storage/smgr/relfilenode.h"
#include "vecexecutor/vectorbatch.h"
#include "utils/hsearch.h"
#include "storage/lock/lwlock.h"
#include "storage/spin.h"
#include "storage/shmem.h"
#include "imcu.h"
#include "imcs_cache_mgr.h"
#include "imcu_storage.h"
#include "storage/cucache_mgr.h"
#include <set>

#define IMCU_CACHE (IMCUCacheMgr::GetInstance())

int IMCStoreDataCacheMgrNumLocks();

typedef struct {
    Oid imcs_oid;
    IMCSDesc *imcs_desc;
} IMCSDesc_Entry;

typedef struct {
    IMCUDesc_Tag cu_tag;
    IMCUDesc *cu_desc;
} IMCUDesc_Entry;

/*
 * This class is to manage imcu Cache.
 * For integer IMCU, we should store compressed data.
 * For string IMCU, because the speed of decompressing data is low,
 * so store source data.
 */
class IMCUCacheMgr : public DataCacheMgr {
public:
    static IMCUCacheMgr *GetInstance(void);
    static void NewSingletonInstance(void);

    int ReserveImcuBlock(DataSlotTag *dataSlotTag, IMCUDesc *cuDescPtr, bool &hasFound, IMCU *imcu);

    int ReserveDataBlock(DataSlotTag *dataSlotTag, int size, bool &hasFound);

    int GetCacheSlotNum();

    CacheDesc *GetCacheSlotDesc(int cuSlotId);

    void DataBlockCompleteIO(int cuSlotId);

    IMCU *GetCUBuf(int cuSlotId);

    void DropRelationImcuCache(const RelFileNode &rnode, int colId);
    CUUncompressedRetCode StartUncompressCU(IMCUDesc *cuDescPtr, CacheSlotId_t slotId, int planNodeId, bool timing,
        int align_size);

    /* imcu_desc */
    uint32 SaveImcuDesc(_in_ Oid imcs_oid, _in_ IMCUDesc *cuDescPtr, _in_ int attnum, _in_ int attlen);

    IMCUDesc *GetImcuDescByHash(_in_ IMCSDesc *imcs_desc, _in_ uint32 cu_id, _in_ int attnum);

    IMCUDesc *GetImcuDesc(_in_ Oid imcs_oid, _in_ uint32 cu_id, _in_ int attnum);

    void DropImcuDesc(_in_ Oid imcs_oid, _in_ uint32 cu_id, _in_ int attnum);

    void IncreaseImcsRowGroupNum(_in_ Oid imcs_oid, _in_ uint32 max_cu_id);

    void IncreaseIMCUDesc(_in_ Oid imcs_oid, _in_ uint32 cu_id, _in_ int attnum);

    void DropImcuColDesc(_in_ Oid imcs_oid, _in_ int attnum);

    /* imcs_desc */

    IMCSDesc *GetImcsDesc(_in_ Oid imcs_oid);

    void SaveImcsDesc(_in_ Oid imcs_oid);

    void DropImcsDesc(_in_ Oid imcs_oid);

    void DropRelationImcuFile(_in_ const RelFileNode &rnode, _in_ IMCSDesc *imcs_desc);

    void DropRelationColImcuFile(_in_ const RelFileNode &rnode, _in_ int col, _in_ IMCSDesc *imcs_desc);

    void AcquireImcsDescLock(_in_ Oid imcs_oid, LWLockMode lock_mode);

    void ReleaseImcsDescLock(_in_ Oid imcs_oid);

    bool AcquireImcsRgLock(_in_ Oid imcs_oid, LWLockMode lock_mode, int rg);

    void ReleaseImcsRgLock(_in_ Oid imcs_oid, int rg);

    void CreateImcsRgLock(_in_ Oid imcs_oid, int rg);

    int64 GetCurrentMemSize();

    HTAB *m_imcs_hash;

    MemoryContext m_imcs_context;

    XLogRecPtr m_xlog_current_lsn;

    XLogRecPtr m_startup_cur_lsn;

    /* Lock for protected m_xlog_current_lsn modify operation When two tables populate at the same time.
     * The m_xlog_lsn_lock needed only when m_xlog_current_lsn is InvalidXLogRecPtr,
     * which means that it is the first time that populate.
     */
    LWLock *m_xlog_lsn_lock;
    /* lock for protected imcs_hash_table operation */
    LWLock *m_imcs_latch;

    std::set<Oid> m_reinit_imcs_set;

    pg_atomic_uint32 m_imcs_cnt;
#ifndef ENABLE_UT
private:
#endif /* ENABLE_UT */

    IMCUCacheMgr() {}
    ~IMCUCacheMgr() {}

    static IMCUCacheMgr *imcu_data_cache;
};

#endif /* define */
